#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include "avplaylist.h"

AvplayListEntry *avplayListCopyEntry(AvplayListEntry *src)
{
    AvplayListEntry *dst = malloc(sizeof(AvplayListEntry));
    if (!dst)
        return NULL;

    memcpy(dst, src, sizeof(AvplayListEntry));
    dst->path = malloc(strlen(src->path) + 1);
    strcpy(dst->path, src->path);
    dst->name = malloc(strlen(src->name) + 1);
    strcpy(dst->name, src->name);
    return dst;
}

AvplayListEntry *avplayListGetEntryByName(AvplayList *list, const char *name)
{
    if (!list)
        return NULL;

    AvplayListEntry *entry = list->head;

    int name_length = strlen(name);

    while (entry)
    {
        if (strcasecmp(entry->name, name) == 0)
            return entry;

        entry = entry->next;
    }

    return NULL;
}

AvplayListEntry *avplayListGetEntryByNumber(AvplayList *list, int n)
{
    if (!list)
        return NULL;

    AvplayListEntry *entry = list->head;

    while (n > 0 && entry)
    {
        n--;
        entry = entry->next;
    }

    if (n != 0)
        return NULL;

    return entry;
}

int avplayListGetNumberByName(AvplayList *list, const char *name)
{
    if (!list)
        return -1;

    AvplayListEntry *entry = list->head;

    int name_length = strlen(name);

    int n = 0;

    while (entry)
    {
        if (strcasecmp(entry->name, name) == 0)
            return n;

        n++;
        entry = entry->next;
    }

    return -1;
}

void avplayListAddEntry(AvplayList *list, AvplayListEntry *entry)
{
    if (!list || !entry)
        return;

    entry->next = NULL;
    entry->previous = NULL;

    if (list->head == NULL)
    {
        list->head = entry;
        list->tail = entry;
    }
    else
    {
        AvplayListEntry *tail = list->tail;
        tail->next = entry;
        entry->previous = tail;
        list->tail = entry;
    }

    list->length++;
}

void avplayListAddEntryByPath(AvplayList *list, char *path)
{
    if (!list || !path)
        return;

    AvplayListEntry *entry = (AvplayListEntry *)calloc(1, sizeof(AvplayListEntry));
    entry->path = malloc(strlen(path) + 1);
    strcpy(entry->path, path);
    entry->name = getFilename(path);

    avplayListAddEntry(list, entry);
}

int avplayListRemoveEntry(AvplayList *list, AvplayListEntry *entry)
{
    if (!list || !entry)
        return 0;

    if (entry->previous)
    {
        entry->previous->next = entry->next;
    }
    else
    {
        list->head = entry->next;
    }

    if (entry->next)
    {
        entry->next->previous = entry->previous;
    }
    else
    {
        list->tail = entry->previous;
    }

    list->length--;
    free(entry->name);
    free(entry);

    if (list->length == 0)
    {
        list->head = NULL;
        list->tail = NULL;
    }

    return 1;
}

int avplayListRemoveEntryByName(AvplayList *list, const char *name)
{
    if (!list)
        return 0;

    AvplayListEntry *entry = list->head;
    AvplayListEntry *previous = NULL;

    int name_length = strlen(name);

    while (entry)
    {
        if (strcasecmp(entry->name, name) == 0)
        {
            if (previous)
            {
                previous->next = entry->next;
            }
            else
            {
                list->head = entry->next;
            }

            if (list->tail == entry)
            {
                list->tail = previous;
            }

            list->length--;
            free(entry->name);
            free(entry);

            if (list->length == 0)
            {
                list->head = NULL;
                list->tail = NULL;
            }

            return 1;
        }

        previous = entry;
        entry = entry->next;
    }

    return 0;
}

void avplayListEmpty(AvplayList *list)
{
    if (!list)
        return;

    AvplayListEntry *entry = list->head;

    while (entry)
    {
        AvplayListEntry *next = entry->next;
        if (entry->name)
            free(entry->name);
        if (entry->path)
            free(entry->path);
        free(entry);
        entry = next;
    }

    list->head = NULL;
    list->tail = NULL;
    list->length = 0;
}

int avplayListGetEntries(AvplayList *playlist, const FileList *filelist)
{
    if (!playlist || !filelist)
        return -1;

    FileListEntry *entry = filelist->head;
    char path[MAX_PATH_LENGTH];

    while (entry)
    {
        if (!entry->is_folder)
        {
            snprintf(path, MAX_PATH_LENGTH, "%s%s", filelist->path, entry->name);
            avplayListAddEntryByPath(playlist, path);
        }
        entry = entry->next;
    }

    return 0;
}
